from scapy.all import *
import threading
from queue import Queue
import sys

# 线程锁，用于防止打印时出现竞争条件
print_lock = threading.Lock()

# 扫描单个端口
def fin_scan(ip, port):
    src_port = RandShort()  # 随机源端口
    fin_packet = IP(dst=ip)/TCP(sport=src_port, dport=port, flags="F")  # 创建FIN包
    response = sr1(fin_packet, timeout=1, verbose=False)  # 发送FIN包并等待响应

    if response:
        if response.haslayer(TCP):
            if response.getlayer(TCP).flags == 0x14:  # RST响应
                with print_lock:
                    print(f"Port {port} is closed on {ip}")
    else:
        with print_lock:
            print(f"Port {port} is open or filtered on {ip}")

# 线程函数，从队列中取出端口并扫描
def threader(ip, q):
    while True:
        port = q.get()
        if port is None:
            break
        fin_scan(ip, port)
        q.task_done()

# 主函数，启动多线程扫描
def main():
    if len(sys.argv) != 4:
        print("Usage: python3 fin_scan.py <ip> <start_port> <end_port>")
        sys.exit()

    ip = sys.argv[1]
    start_port = int(sys.argv[2])  # 转换成整数
    end_port = int(sys.argv[3])    # 转换成整数

    # 创建队列并填充端口号
    q = Queue()
    for port in range(start_port, end_port + 1):
        q.put(port)

    # 启动线程池
    num_threads = 100
    threads = []
    for _ in range(num_threads):
        t = threading.Thread(target=threader, args=(ip, q))
        t.start()
        threads.append(t)

    # 等待队列被清空
    q.join()

    # 停止线程
    for _ in range(num_threads):
        q.put(None)
    for t in threads:
        t.join()

if __name__ == "__main__":
    main()
# pip install scapy
# sansjtw